// Package redis_demo article_voted_demo
// @Title redis_demo
// @Description
// @Author  == 琳琳也叫王木木 ==  2021-12-17 11:02
// @Create  2021-12-17 11:02
package redis_demo

import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v8" // 注意导入的是新版本
	"time"
)

var ARTICLE_EXPIRE_SECONDS int = 7 * 86400 // 设置文章投票的过期时间
var VOTE_SCORE = 432                       // 文章评分单位 每次点赞 评分增加432分
var TIME_Z_SET = "time:"                   // 文章发布时间有序集合名称
var SCORE_Z_SET = "score:"                 // 文章评分有序集合名称
var rdb *redis.Client

/**
初始化redis连接对象
*/
func initRedisConn() (err error) {
	rdb = redis.NewClient(&redis.Options{
		Addr:     "127.0.0.1:6379", // host
		Password: "",               // 密码
		DB:       0,                // 使用数据库名称
		PoolSize: 100,              // 连接池大小
	})
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	_, err = rdb.Ping(ctx).Result()
	return err
}

/**
文章点赞功能
*/
func articleVoted(ctx context.Context, userId string, articleId int) {
	cutOff := int(time.Now().Unix()) - ARTICLE_EXPIRE_SECONDS // 获取时间差
	fmt.Println(cutOff)
	ctf := rdb.ZScore(ctx, TIME_Z_SET, fmt.Sprint(articleId)).Val()
	if float64(cutOff) > ctf {
		fmt.Println("无法点赞，发布文章太老")
		return
	}
	voted := fmt.Sprintf("voted:%d", articleId)        // 组合点赞的键
	articleStr := fmt.Sprintf("article:%d", articleId) // 组合点赞的键

	rdb.SAdd(ctx, voted, userId) // 为点赞集合新增一个点赞用户
	rdb.ZIncrBy(ctx, SCORE_Z_SET, float64(VOTE_SCORE), SCORE_Z_SET)
	rdb.HIncrBy(ctx, articleStr, "votes", 1) // 文章信息哈希表中，对votes字段+1
}

/**
发布文章功能
*/
func publish_article(ctx context.Context, user, link, title string) (int, error) {
	// -------------------------------------------  初始化数据   --------------------------------------------------------

	articleId := rdb.Incr(ctx, "article:").Val() // 生成一个新的文章ID

	voted := fmt.Sprintf("voted:%d", articleId) // 组合点赞的键

	article := fmt.Sprintf("article:%d", articleId)

	articleInfo := map[string]interface{}{
		"title":  title,
		"link":   link,
		"poster": user,
		"time":   time.Now().Unix(),
		"votes":  1,
	} // 组合文章数据信息

	scoreDict := redis.Z{
		Score:  float64(time.Now().Unix()) + float64(VOTE_SCORE),
		Member: articleId,
	}

	timeDict := redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: articleId,
	}

	// --------------------------------------------  执行redis操作   ----------------------------------------------------

	num := rdb.SAdd(ctx, voted, user) // 将作者添加到点赞表
	fmt.Println("添加点赞集合", num)
	success := rdb.Expire(ctx, voted, time.Duration(ARTICLE_EXPIRE_SECONDS)*time.Second) // 为文章点赞的功能设置过期时间
	fmt.Println("添加过期时间", success)
	success = rdb.HMSet(ctx, article, articleInfo) // 将文章信息添加到文章列表
	fmt.Println("添加文章信息", success)
	_, err := rdb.ZAdd(ctx, SCORE_Z_SET, &scoreDict).Result() // 初始化文章评分
	if err != nil {
		fmt.Println("article score set init failed !", err)
		return -1, err
	}
	_, err = rdb.ZAdd(ctx, TIME_Z_SET, &timeDict).Result() // 初始化文章发布时间
	if err != nil {
		fmt.Println("publish time set init failed !", err)
		return -1, err
	}

	return int(articleId), nil
}

/**
获取文章列表
*/
func getArticles(ctx context.Context, page int, order string) {

}

func V8Example() {
	ctx := context.Background()
	if err := initRedisConn(); err != nil {
		return
	}

	articleId, err := publish_article(ctx, "wulinlin", "https://www.runoob.com/redis/sorted-sets-zadd.html", "how can i do for my love?")
	if err != nil {
		fmt.Println("文章发布失败", err)
		return
	}
	fmt.Println("文章发布成功,id:", articleId)
	articleVoted(ctx, "34", articleId)
}
